﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Optimization;
using com.nm;
using Microsoft.Ajax.Utilities;
using george.Web;

namespace com.nm.library {
	public static class JavaScriptHelper {
		const string KEY = "JSP";
		static IList<BundlePacker> __packers;
		/// <summary>
		/// 把需要使用的JS包添加到页面
		/// </summary>
		/// <param name="page">要添加的页面</param>
		/// <param name="packers">JS包名称，可以多个，按顺序输出</param>
		/// <returns></returns>
		public static System.Web.UI.Page AddJavaScriptPacker(this System.Web.UI.Page page, params string[] packers) {
			if (page.Items[JavaScriptHelper.KEY] == null) {
				page.Items[JavaScriptHelper.KEY] = new List<string>();
			}
			var packerNameList = (List<string>)page.Items[JavaScriptHelper.KEY];
			foreach (var str in packers) {
				if (packerNameList.Contains(str)) continue;
				var packer = getPacker(str);
				if (packer != null)
					packerNameList.Add(packer.Name);
			}
			return page;
		}
		/// <summary>
		/// 把需要使用的JS包添加到页面
		/// </summary>
		/// <param name="page">要添加的页面</param>
		/// <param name="packers">JS包名称，可以多个，按顺序输出</param>
		/// <returns></returns>
		public static System.Web.UI.Page AddJavaScriptPacker(this System.Web.UI.MasterPage page, params string[] packers) {
			return AddJavaScriptPacker(page.Page, packers);
		}
		/// <summary>
		/// 输出添加的JS包
		/// </summary>
		/// <param name="page">页面</param>
		/// <returns></returns>
		/// <see cref="com.nm.library.BundleManager"/>
		public static HtmlString GetJavaScript(this System.Web.UI.Page page, bool Optimization = true) {
			var sb = new StringBuilder();
			//sb.Append(page.VirtualPath);
			var url = page.UniqueID;

			//sb.AppendLine(url);
			var bundlePath = url.Insert(0, "~/bundles/").Replace("//", "/");
			Log.WriteLog(bundlePath, "GetJavaScript");
			//是否已经存在
			if (BundleManager.IsExists(bundlePath) == false) {
				var bundle = new ScriptBundle(bundlePath);
				//是否添加了JS依赖包
				if (page.Items[JavaScriptHelper.KEY] != null) {
					var packerNameList = (List<string>)page.Items[JavaScriptHelper.KEY];
					if (packerNameList.Count > 0) {
						foreach (var name in packerNameList) {
							var packer = getPacker(name);
							if (packer != null) {
								bundle.Include(packer.Files.ToArray());
							}
						}
					}
				}
				//添加本页面JS
				//if (string.IsNullOrWhiteSpace(area)) {
				//	bundle.Include(String.Format("~/Scripts{0}.js", url));
				//} else {
				//	bundle.Include(String.Format("~/Scripts/Areas{0}.js", url));
				//}
				BundleManager.Add(bundle);
			}
			sb.Append(Scripts.Render(bundlePath));
			var result = new HtmlString(sb.ToString());
			return result;
		}
		/// <summary>
		/// 输出添加的JS包
		/// </summary>
		/// <param name="page">页面</param>
		/// <returns></returns>
		/// <see cref="com.nm.library.BundleManager"/>
		public static HtmlString GetJavaScript(this System.Web.UI.MasterPage page, bool Optimization = true) {
			return GetJavaScript(page.Page, Optimization);
		}
		/// <summary>
		/// 输出JS包
		/// </summary>
		/// <param name="page">页面</param>
		/// <param name="packers">要输出的包名，可以多个，按顺序输出</param>
		/// <returns></returns>
		/// <see cref="com.nm.library.BundleManager"/>
		public static HtmlString GetJavaScript(this System.Web.UI.Page page, params string[] packers) {
			var sb = new StringBuilder();
			//sb.Append(page.VirtualPath);
			var url = page.UniqueID + "/" + string.Join("-", packers);
			//sb.AppendLine(url);
			var bundlePath = url.Insert(0, "~/bundles/").Replace("//", "/");
			//是否已经存在
			if (BundleManager.IsExists(bundlePath) == false) {
				var bundle = new ScriptBundle(bundlePath);
				foreach (var name in packers) {
					var packer = getPacker(name);
					if (packer != null) {
						bundle.Include(packer.Files.ToArray());
					}
				}
				BundleManager.Add(bundle);
			}
			sb.Append(Scripts.Render(bundlePath));

			var result = new HtmlString(sb.ToString());
			return result;
		}
		public static HtmlString GetJavaScript(this System.Web.UI.Page page, bool Optimization, params string[] packers) {
			if (Optimization) {
				return page.GetJavaScript(packers);
			}
			var sb = new StringBuilder();
			foreach (var name in packers) {
				var packer = getPacker(name);
				if (packer == null) continue;
				foreach (var jsUrl in packer.Files) {
					sb.Append(page.getJavaScriptTag(jsUrl));
				}
			}
			var result = new HtmlString(sb.ToString());
			return result;
		}
		/// <summary>
		/// 输出JS包
		/// </summary>
		/// <param name="page">页面</param>
		/// <param name="packers">要输出的包名，可以多个，按顺序输出</param>
		/// <returns></returns>
		/// <see cref="com.nm.library.BundleManager"/>
		public static HtmlString GetJavaScript(this System.Web.UI.MasterPage page, params string[] packers) {
			return GetJavaScript(page.Page, packers);
		}
		public static HtmlString GetJavaScript(this System.Web.UI.MasterPage page, bool Optimization, params string[] packers) {
			return GetJavaScript(page.Page, Optimization, packers);
		}
		static BundlePacker getPacker(string name)
		{
			return __packers == null 
				? null 
				: __packers.FirstOrDefault(item => item.Name.CompareTo(name) == 0);
		}

		internal static void AddPacker(BundlePacker packer) {
			if (__packers == null) __packers = new List<BundlePacker>();
			var exists = __packers.Count(item => item.Name.CompareTo(packer.Name) == 0) > 0;
			if (exists) throw new ArgumentException(string.Format("{0} 已经存在", packer.Name));

			__packers.Add(packer);
		}
		public static IHtmlString Script(this System.Web.UI.MasterPage page, params string[] urls) {
			return Script(page.Page, urls);
		}
		public static IHtmlString Script(this System.Web.UI.Page page, params string[] urls) {
			var bundleDirectory = "~/bundles/" + BundleManager.MakeBundleName("js", urls);
			var bundle = BundleTable.Bundles.GetBundleFor(bundleDirectory);
			if (bundle != null) return Scripts.Render(bundleDirectory);
			var transform = new System.Web.Optimization.JsMinify();
			//var transform = new JavascriptObfuscator();
			bundle = new ScriptBundle(bundleDirectory).Include(urls);
			bundle.Transforms.Add(transform);
			BundleTable.Bundles.Add(bundle);
			return Scripts.Render(bundleDirectory);
		}
		public static IHtmlString Script(this System.Web.UI.MasterPage page, bool Optimization, params string[] urls) {
			return Script(page.Page, Optimization, urls);
		}
		public static IHtmlString Script(this System.Web.UI.Page page, bool Optimization, params string[] urls) {
			if (Optimization) {
				return page.Script(urls);
			}
			var sb = new StringBuilder();
			foreach (var url in urls) {
				sb.Append(page.getJavaScriptTag(url));
			}
			return new HtmlString(sb.ToString());
		}
		static string getJavaScriptTag(this System.Web.UI.Page page, string url){
			return JavaScriptHelper.getJavaScriptTag(page.ResolveClientUrl(url), page.MapPath(url));
		}
		static string getJavaScriptTag(string url,string fileName) {
			if (!File.Exists(fileName)) return string.Empty;
			var ver = DateTime.Now.Ticks;
			if (myCache.Exists(url)) {
				ver = myCache.Get<long>(url);
			} else {
				var dp = new System.Web.Caching.CacheDependency(fileName);
				myCache.Insert(url, ver, dp);
			}
			return string.Format("<script src=\"{0}?v={1}\" type=\"text/javascript\"></script>", url, ver);
		}
	}//end class
}//end namespace